# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl Proc-RPC.t'

#########################

# change 'tests => 1' to 'tests => last_test_to_print';

use Test::More;

BEGIN { use_ok('Proc::RPC') };
use Proc::RPC;


# Pruebas del método read_output_child
{
	open my $f, '<', 't/ficherito.txt'; 
	local undef $/;
	my $ficherito = <$f>;
	close $f;
	
	is(Proc::RPC->read_child_output('t/ficherito.txt'), $ficherito, 'Testing the read_child_output method');	
}

# Basic test for join method
{
	sub increment_array
	{
		my ($inc, @array) = @_;
		$_ += $inc for(@array);
		return @array;
	}
	
	my $inc = 34;
	my @a = (1,2,3,4,5,6,7);
	my @b = increment_array($inc, @a);
	
	my $proc = Proc::RPC->new();
	$proc->rpc(\&increment_array, ($inc, @a));
	my $r = $proc->join();

	# Join retorna un objeto Proc::RPC::Result	
	ok(ref $r eq 'Proc::RPC::Result', 'Expecting a Proc::RPC::Result object');
	
	my @result = @{$r->result()};	
	is_deeply(\@b,\@result, "Probando el join - Devolviendo listas"); 
}

# Join method returning sub routines
{
	sub return_sub
	{
		return sub { 'Soy algo que devuelve una subrutina, devuelta por una subrutina. Parámetros = ' . @_ }
	}
	
	my $proc = Proc::RPC->new();
	$proc->rpc(\&return_sub, 'param1', 'param2', 'param3');
	my $r = $proc->join();
	
	is_deeply(&{$r->result()->[0]}, &{return_sub()}, "Join method returning a sub routine");
}



###############################################################################
# Simple test using RPC.
###############################################################################
{
  my $p = Proc::RPC->new();
  $p->rpc(sub { return { a => 1, b => 2, c => [ @_ ], d => 5 } }, 4, 7, 9);
  my $ret = $p->join();
  my $expected = Proc::RPC::Result->new( 
                 'stderr' => '',
                 'status' => '0',
                 'stdout' => '',
                 'result' => [
                                 {
                                   'c' => [
                                            4,
                                            7,
                                            9
                                          ],
                                   'a' => 1,
                                   'b' => 2,
                                   'd' => 5
                                 }
                               ] );
               
  is(%{$ret->result()->[0]}, %{$expected->result()->[0]}, "Simple test using RPC");
}


###############################################################################
# Standard Output capture test.
###############################################################################
{
  my $stdout_test = "Standard Output capture test";
  my $p = Proc::RPC->new();
  $p->rpc(sub { print $stdout_test });
  my $ret = $p->join();
  is($ret->stdout(), $stdout_test, $stdout_test);
}

###############################################################################
# Standard Error capture test.
###############################################################################
{
  my $stderr_test = "Standard Error capture test";
  my $p = Proc::RPC->new();
  $p->rpc(sub { print STDERR $stderr_test });
  my $ret = $p->join();
  is($ret->stderr(), $stderr_test, $stderr_test);
}


###############################################################################
# Parallel Pi Calculation.
###############################################################################
{
  my $pi_part = sub {
    my ($id, $N, $np) = @_;
    my $sum = 0;

    foreach (grep { $_ % $np eq $id } (0 .. $N)) {
      my $x = ($_ + 0.5) / $N;
      $sum += 4 / (1 + $x * $x)
    }

    return $sum / $N;
  };

  my $N = 50000;
  my $np = 5;

  my @running;

  foreach (0..$np - 1) {
    my $p = Proc::RPC->new();
    $p->rpc($pi_part, $_, $N, $np);
    push(@running, $p);
  }

  my $sum;
  while (@running != 0) {
    my @alive;
    foreach (@running) {
      if ($_->poll()) {
        push(@alive, $_);
      } else {
        my $ret = $_->join();
        $sum += shift @{$ret->result()};
      }
    }
    @running = @alive;
  }
  is($sum, 3.14163265322313, "Parallel Pi Calculation");
}








done_testing();
